/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package generation;

import ASAExpr.ASAExprIdent;
import exception.VariableNonDeclareeException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 *
 * @author FM & KB
 */
public class GestionVariables {

    private static Map<String, LinkedList<Map<String, ASAExprIdent>>> ensVariables = null;

    private GestionVariables() {
        //mapVariables = new HashMap<String,ASAExprIdent>();
    }

    public final static ASAExprIdent getVariable(String nomFonction, String nomVariable)
            throws VariableNonDeclareeException {

        if (!ensVariables.containsKey(nomFonction)) {
            throw new VariableNonDeclareeException(nomFonction);
        }

        LinkedList<Map<String, ASAExprIdent>> temp = (LinkedList<Map<String, ASAExprIdent>>) ensVariables.get(nomFonction).clone();
        //Test de l'existance de la variable dans tout les niveaux inférieurs
        //ou égaux au niveau actuel.

        boolean trouve = temp.getLast().containsKey(nomVariable);
        while (!trouve && !temp.isEmpty()) {
            temp.removeLast();
            if(temp.isEmpty()){
                trouve = false;
                break;
            }
            trouve = temp.getLast().containsKey(nomVariable);
        }

        //Si on n'a pas trouvé la variable, on l'ajoute dans le niveau actuel.
        if (!trouve) {
            throw new VariableNonDeclareeException(nomVariable);
        } else {
            return temp.getLast().get(nomVariable);
        }
    }

    public final static void declarerVariable(String nomFonction, String nomVariable) {
        System.err.println("put : " + nomVariable + " in level " + ensVariables.size());
        ensVariables.get(nomFonction).getLast().put(nomVariable, new ASAExprIdent(nomVariable));

    }

    public static Map<String, Integer> listeVariables() {
        Map<String, Integer> map = new HashMap<String, Integer>();
        if (ensVariables != null && !ensVariables.isEmpty()) {
            //Récupération de la LinkedList associée a la fonction main
            LinkedList<Map<String, ASAExprIdent>> val = ensVariables.get("main");
            //Pour chaque niveau de variable    
            for (Map<String, ASAExprIdent> niveau : val) {
                for (String nomVariable : niveau.keySet()) //Pour chaque variable de niveau
                {
                    map.put(nomVariable, niveau.get(nomVariable).getValeur());
                }
            }
        }
        return map;
    }

    public static void ajouterNiveau(String nomFonction) {
        Map<String, ASAExprIdent> mapVariableVide = new HashMap<String, ASAExprIdent>();
        ensVariables.get(nomFonction).addLast(mapVariableVide);
    }

    public static void retirerNiveau(String nomFonction) {
        ensVariables.get(nomFonction).removeLast();
    }

    public static void ajouterFonction(String nomFonction) {
        if (ensVariables == null) {
            ensVariables = new HashMap<String, LinkedList<Map<String, ASAExprIdent>>>();
        }
        LinkedList<Map<String, ASAExprIdent>> listeVariables = new LinkedList<Map<String, ASAExprIdent>>();
        ensVariables.put(nomFonction, listeVariables);
        //Création du premier niveau de la pile.
        ajouterNiveau(nomFonction);
    }

    public static void reinitialiser() {
        if (ensVariables != null) {
            ensVariables.clear();
            ensVariables = null;
        }
    }

    public String afficherContenuMemoire() {
        String result = "";
        if (ensVariables == null || ensVariables.isEmpty()) {
            result = "Aucune variable.";
        } else {
            int i = 0;
            for (String fonction : ensVariables.keySet()) {
                for (Map<String, ASAExprIdent> map : ensVariables.get(fonction)) {
                    result += "Level" + fonction + "\n";
                    for (String nomVariable : map.keySet()) {
                        result += nomVariable + " " + map.get(nomVariable).getValeur() + '\n';
                    }
                    i++;
                }
            }
        }
        return result;
    }
}
